package com.ls.fw.office.poi.excel;

/**
 * @ProjectName: 
 * @Copyright: 2014 lisheng  All Right Reserved.
 * @address: toughheart@163.com
 * @date: 2015年10月8日 下午10:17:02
 * @Description: 本内容未经本人允许禁止使用、转发.
 */

import java.io.IOException;
import java.io.OutputStream;
import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import com.ls.fw.commons.core.utils.collections.CollectionUtils;
import com.ls.fw.commons.core.utils.collections.MapUtils;
import com.ls.fw.commons.core.utils.collections.MapUtils.CollectionMapper;
import com.ls.fw.commons.core.utils.collections.MapUtils.MapMapper;
import com.ls.fw.office.poi.excel.handler.ExcelHandler;
import com.ls.fw.office.poi.excel.handler.IExcelHandler;
import com.ls.fw.office.poi.excel.support.mapper.CellMapper;
import com.ls.fw.office.poi.utils.PoiPublicUtil;
import com.ls.fw.office.poi.utils.PoiReflectorUtil;


/**
 * 
 * @author lisheng
 * @date 2015年10月8日 下午10:17:02
 * @version V1.0 
 */
public class ExcelExport {
	
	protected IExcelHandler handler = null;
	
	protected List<String> head;
	protected Map<Integer,String> headMap;
	
	protected int headIndex = 0;
	protected int rowLastIndex = 1;
	
	
	public ExcelExport(OutputStream out) {
		super();
		this.handler = new ExcelHandler(out);
	}
	public ExcelExport(String path) {
		super();
		this.handler = new ExcelHandler(path);
	}

	public ExcelExport(OutputStream out,int headIndex) {
		super();
		this.handler = new ExcelHandler(out);
		this.headIndex = headIndex;
		this.rowLastIndex = headIndex + 1;
	}
	public ExcelExport(String path,int headIndex) {
		super();
		this.handler = new ExcelHandler(path);
		this.headIndex = headIndex;
		this.rowLastIndex = headIndex + 1;
	}
	public ExcelExport(IExcelHandler handler) {
		super();
		this.handler = handler;
	}
	public ExcelExport(IExcelHandler handler,int headIndex) {
		super();
		this.handler = handler;
		this.headIndex = headIndex;
		this.rowLastIndex = headIndex + 1;
	}
	 
	public ExcelExport setHead(Map<Integer,String> headMap){
		if(this.head==null){
			this.head = new ArrayList<String>();
		}
		CollectionUtils.traversal(headMap, new CollectionMapper() {
			
			@Override
			public boolean next(Object arg0, Object arg1) {
				int index = Integer.valueOf(String.valueOf(arg0));
				String valueString = String.valueOf(arg1);
				head.add(index+1, valueString);
				return true;
			}
		});
		this.headMap = headMap;
		setHead();
		return this;
	}
	
	private ExcelExport setHead(){
		CollectionUtils.traversal(headMap, new CollectionMapper() {
			
			@Override
			public boolean next(Object arg0, Object arg1) {
				int index = Integer.valueOf(String.valueOf(arg0));
				String valueString = String.valueOf(arg1);
				handler.createHead(headIndex, index, valueString);
				return true;
			}
		});
		return this;
	}
	
	public ExcelExport setHead(List<String> head){
		this.head = head;
		if(this.head!=null && headMap==null){
			headMap = new HashMap<Integer,String>();
			int index = 0;
			for (String string : head) {
				headMap.put(index++, string);
			}
			setHead();
		}
		return this;
	}
	

	/**
	 * 
	 * @author lisheng
	 * @date 2016年6月14日 下午9:29:58
	 * @version V1.0
	 * @param heads
	 */
	public ExcelExport setHead(String... heads){
		if(heads!=null){
			this.head = Arrays.asList(heads);
		}
		if(this.head!=null && headMap==null){
			headMap = new HashMap<Integer,String>();
			int index = 0;
			for (String string : head) {
				headMap.put(index++, string);
			}
			setHead();
		}
		return this;
	}
	
	/**
	 * 添加一条记录
	 * 
	 * @author lisheng
	 * @date 2016年6月14日 下午9:29:54
	 * @version V1.0
	 * @param map
	 */
	public ExcelExport add(Map<String,Object> map){
		 add(map, null);
		 return this;
	}
	
	
	/**
	 * 添加一条记录
	 * 
	 * @author lisheng
	 * @date 2016年6月14日 下午9:29:52
	 * @version V1.0
	 * @param map
	 * @param cellMapper
	 */
	public ExcelExport add(Map<String,Object> map, final CellMapper cellMapper){
		int colIndex = 0;//列序号
		if(CollectionUtils.isNotEmpty(head)){
			int index = 0;
			for (String h : head) {
				Object value = map.get(h);
				if(cellMapper != null){
					value = cellMapper.mapper(index++,h, value);
				}
				this.handler.addCell(rowLastIndex, colIndex++, value);
			}
		}else{
			MapUtils.traversal(map, new MapMapper() {
				
				@Override
				public boolean next(Object name, Object value,int index) {
					Object dObject = value;
					if(cellMapper != null){
						dObject = cellMapper.mapper(index,String.valueOf(name), dObject);
					}
					handler.addCell(rowLastIndex, index, dObject);
					return true;
				}
			});
		}
		++rowLastIndex;//行序号
		return this;
	}
	
	/**
	 * 添加一条记录
	 * 
	 * @author lisheng
	 * @date 2016年6月14日 下午9:29:43
	 * @version V1.0
	 * @param object
	 */
	public ExcelExport add(Object object ){
		add(object, null);
		return this;
	}
	
	/**
	 * 添加一条记录
	 * 
	 * @author lisheng
	 * @date 2016年6月14日 下午9:29:35
	 * @version V1.0
	 * @param object
	 * @param cellMapper
	 */
	public ExcelExport add(Object object,final CellMapper cellMapper){
		if(object==null){
			return this;
		}
		int colIndex = 0;//列序号
		if(object instanceof Map){
			Map map = (Map)object;
			if(CollectionUtils.isNotEmpty(head)){
				int index = 0;
				for (String h : head) {
					Object value = map.get(h);
					if(cellMapper != null){
						value = cellMapper.mapper(index++,h, value);
					}
					this.handler.addCell(rowLastIndex, colIndex++, value);
				}
			}else{
				MapUtils.traversal(map, new MapMapper() {
					
					@Override
					public boolean next(Object name, Object value,int index) {
						Object dObject = value;
						if(cellMapper != null){
							dObject = cellMapper.mapper(index,String.valueOf(name), dObject);
						}
						handler.addCell(rowLastIndex, index, dObject);
						return true;
					}
				});
			}
		}else if(object instanceof Collection){
			Collection c = (Collection)object;
			int index = 0;
			for (Object value : c) {
				if(cellMapper != null){
					value = cellMapper.mapper(index++,head.get(index), value);
				}
				handler.addCell(rowLastIndex, colIndex++, value);
			}
		}else{
			PoiReflectorUtil f = PoiReflectorUtil.forClass(object.getClass());
			if(CollectionUtils.isNotEmpty(head)){
				int index = 0;
				for (String h : head) {
					Object value = f.getValue(object, h);
					if(cellMapper != null){
						value = cellMapper.mapper(index++,h, value);
					}
					handler.addCell(rowLastIndex, colIndex++, value);
				}
			}else{
				Field[] fs = PoiPublicUtil.getClassFields(object.getClass());
				int index = 0;
				for (Field field : fs) {
					Object value = f.getValue(object, field.getName());
					if(cellMapper != null){
						value = cellMapper.mapper(index++,field.getName(), value);
					}
					handler.addCell(rowLastIndex, colIndex++, value);
				}
			}
		}
		++rowLastIndex;//行序号
		return this;
	}
	
	/**
	 * 添加多条记录
	 * @author lisheng
	 * @date 2016年6月14日 下午9:29:27
	 * @version V1.0
	 * @param list
	 * @param cellMapper
	 */
	public ExcelExport add(Collection list,final CellMapper cellMapper){
		if(CollectionUtils.isNotEmpty(list)){
			for (Object object : list) {
				this.add(object,cellMapper);
			}
		}
		return this;
	}
	
	/**
	 * 添加多条记录
	 * 
	 * @author lisheng
	 * @date 2016年6月14日 下午9:29:14
	 * @version V1.0
	 * @param list
	 */
	public ExcelExport add(Collection list){
		add(list, null);
		return this;
	}
	
	
	/**
	 * 保存
	 * @author lisheng
	 * @date 2016年6月14日 下午9:28:57
	 * @version V1.0
	 * @throws IOException
	 */
	public void save() throws IOException{
		this.handler.save();
	}

	public IExcelHandler getHandler() {
		return this.handler;
	}
	public ExcelExport setHandler(IExcelHandler handler) {
		this.handler = handler;
		return this;
	}
	public Map<Integer, String> getHeadMap() {
		return this.headMap;
	}
	public ExcelExport setHeadMap(Map<Integer, String> headMap) {
		this.headMap = headMap;
		return this;
	}
	public int getHeadIndex() {
		return this.headIndex;
	}
	public ExcelExport setHeadIndex(int headIndex) {
		this.headIndex = headIndex;
		return this;
	}
	public int getRowLastIndex() {
		return this.rowLastIndex;
	}
	public ExcelExport setRowLastIndex(int rowLastIndex) {
		this.rowLastIndex = rowLastIndex;
		return this;
	}
	public List<String> getHead() {
		return this.head;
	}
}